﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.LightSwitch;
using Microsoft.LightSwitch.Security.Server;
using Microsoft.LightSwitch.Details;
using System.Linq.Expressions;

namespace LightSwitchApplication
{
    public partial class ApplicationDataService
    {       
        partial void SaveChanges_Executing()
        {
            EntityChangeSet changes = this.DataWorkspace.ApplicationData.Details.GetChanges();

            foreach (var item_loopVariable in changes.ModifiedEntities)
            {
                //IEntityObject item = item_loopVariable as IEntityObject;
                setModifiedInfo(item_loopVariable);
                createAuditTrail(item_loopVariable);
            }

            foreach (var item_loopVariable in changes.AddedEntities)
            {
                //IEntityObject item = item_loopVariable as IEntityObject;
                setCreatedInfo(item_loopVariable);
                createAuditTrail(item_loopVariable);
            }

            foreach (var item_loopVariable in changes.DeletedEntities)
            {
                //IEntityObject item = item_loopVariable as IEntityObject;
                createAuditTrail(item_loopVariable);
            }
        }

        private void setCreatedInfo(IEntityObject item)
        {

            foreach (var prop_loopVariable in item.Details.Properties.All().OfType<Microsoft.LightSwitch.Details.IEntityStorageProperty>().Where(x => x.Name.StartsWith("Created")))
            {
                //IEntityStorageProperty prop = prop_loopVariable as IEntityStorageProperty;
                if (prop_loopVariable.Name == "CreatedDate")
                {
                    prop_loopVariable.Value = DateTime.Now;
                }

                if (prop_loopVariable.Name == "CreatedBy")
                {
                    prop_loopVariable.Value = this.Application.User.Name;
                }
            }
        }

        private void setModifiedInfo(IEntityObject item)
        {

            foreach (var prop_loopVariable in item.Details.Properties.All().OfType<Microsoft.LightSwitch.Details.IEntityStorageProperty>().Where(x => x.Name.StartsWith("Modified")))
            {
                //IEntityStorageProperty prop = prop_loopVariable as IEntityStorageProperty;
                if (prop_loopVariable.Name == "ModifiedDate")
                {
                    prop_loopVariable.Value = DateTime.Now;
                }

                if (prop_loopVariable.Name == "ModifiedBy")
                {
                    prop_loopVariable.Value = this.Application.User.Name;
                }
            }

        }

        private void createAuditTrail(IEntityObject item)
        {
            dynamic audit = this.DataWorkspace.ApplicationData.AuditLogs.AddNew();
            audit.EntityId = 0;
            audit.EntityName = item.Details.DisplayName;
            audit.ChangeDate = DateTime.Now;
            audit.ChangedBy = this.Application.User.FullName;
            audit.ChangeType = (item.Details.EntityState.ToString() == "Added" ? "Вставка" : 
                (item.Details.EntityState.ToString() == "Modified" ? "Изменение" : 
                    (item.Details.EntityState.ToString() == "Deleted" ? "Удаление" : 
                        item.Details.EntityState.ToString())));

            dynamic newvals = "\n";
            dynamic oldvals = "\n";

            if (item.Details.EntityState == EntityState.Deleted)
            {
                oldvals = string.Format("\n{0} {1}:", item.Details.DisplayName, item.Details.EntityState);
            }
            else if (item.Details.EntityState == EntityState.Added)
            {
                newvals = string.Format("\n{0} {1}:", item.Details.DisplayName, item.Details.EntityState);
            }

            bool isAuditableEntity = false;
            foreach (var prop in item.Details.Properties.All().OfType<Microsoft.LightSwitch.Details.IEntityTrackedProperty>().Where(x => x.Name != "Id" && x.Name != "ModifiedDate" && x.Name != "ModifiedBy" && (!x.Name.Contains("Image"))))
            {
                isAuditableEntity = true;
                //prop = prop_loopVariable;
                if (item.Details.EntityState == EntityState.Modified)
                {
                    if (!object.Equals(prop.Value, prop.OriginalValue))
                    {
                        oldvals += string.Format("\n{0}: {1}", prop.DisplayName, prop.OriginalValue);
                        newvals += string.Format("\n{0}: {1}", prop.DisplayName, prop.Value);
                    }
                }
                else if (item.Details.EntityState == EntityState.Added)
                {
                    newvals += string.Format("\n{0}: {1}", prop.DisplayName, prop.Value);
                }
                else
                {
                    oldvals += string.Format("\n{0}: {1}", prop.DisplayName, prop.Value);
                }
            }
            if (isAuditableEntity)
            {
                var prop_Id = item.Details.Properties.All().OfType<Microsoft.LightSwitch.Details.IEntityTrackedProperty>().Where(x => x.Name == "Id").First();
                if (prop_Id != null)
                {
                    audit.EntityId = (Int32)prop_Id.Value;
                }

                if (item.Details.EntityState == EntityState.Added)
                {
                    audit.NewValues = newvals.Replace("\n\n", "");
                }
                else if (item.Details.EntityState == EntityState.Deleted)
                {
                    audit.OriginalValues = oldvals.Replace("\n\n", "");
                }
                else
                {
                    audit.OriginalValues = oldvals.Replace("\n\n", "");
                    audit.NewValues = newvals.Replace("\n\n", "");
                }
            }
        }

        partial void SalesOrders_CanDelete(ref bool result)
        {

        }

        partial void SalesOrders_Deleting(SalesOrder entity)
        {
        }

        partial void Addresses_Inserted(Address entity)
        {
            if (entity.Shop != null && entity.Shop.ShopSalesPerson == null && entity.StateProvince != null && entity.StateProvince.SalesPerson !=null)
            {
                entity.Shop.ShopSalesPerson = entity.StateProvince.SalesPerson;
            }
        }

        partial void Addresses_Updated(Address entity)
        {
            if (entity.Shop != null && entity.Shop.ShopSalesPerson == null && entity.StateProvince != null && entity.StateProvince.SalesPerson != null)
            {
                entity.Shop.ShopSalesPerson = entity.StateProvince.SalesPerson;
            }
        }

        partial void Customers_Filter(ref Expression<Func<Customer, bool>> filter)
        {
            // filter = e => e.IntegerProperty == 0;
            if (!(this.Application.User.HasPermission(Permissions.CanEditCustomer) || this.Application.User.HasPermission(Permissions.CanSearchCustomer)))
            {
                if (this.Application.User.HasPermission(Permissions.CanManageMyShop)) //sales person assigned to shop
                {
                    filter = e => e.CustomerShops.Where(shop => shop.ShopSalesPerson.aspnet_Profile.PropertyValuesString == this.Application.User.FullName).Count() > 0;
                }
                else //customer
                {
                    filter = e => e.aspnet_Profile.PropertyValuesString == this.Application.User.FullName;
                }
            }
        }
        partial void Shops_Filter(ref Expression<Func<Shop, bool>> filter)
        {
            if (!(this.Application.User.HasPermission(Permissions.CanEditShop)))
            {
                if (this.Application.User.HasPermission(Permissions.CanManageMyShop)) //sales person assigned to shop
                {
                    filter = e => e.ShopSalesPerson.aspnet_Profile.PropertyValuesString == this.Application.User.FullName;
                }
                else //customer, shop owner
                {
                    filter = e => e.ShopCustomer.aspnet_Profile.PropertyValuesString == this.Application.User.FullName;
                }
            }
        }
        partial void SalesOrders_Filter(ref Expression<Func<SalesOrder, bool>> filter)
        {
            if (!(this.Application.User.HasPermission(Permissions.CanEditSalesOrder)))
            {
                if (this.Application.User.HasPermission(Permissions.CanManageMySalesOrder))//sales person assigned to shop
                {
                    filter = e => e.OrderShop.ShopSalesPerson.aspnet_Profile.PropertyValuesString == this.Application.User.FullName;
                }
                else //customer, shop owner
                {
                    filter = e => e.OrderShop.ShopCustomer.aspnet_Profile.PropertyValuesString == this.Application.User.FullName;
                }
            }
        }
        partial void SalesPersons_Filter(ref Expression<Func<SalesPerson, bool>> filter)
        {
            if (!(this.Application.User.HasPermission(Permissions.CanEditSalesPerson)))
            {
                if (this.Application.User.HasPermission(Permissions.CanManageMyVisit) || this.Application.User.HasPermission(Permissions.CanManageMySalesOrder))
                {
                    filter = e => e.aspnet_Profile.PropertyValuesString == this.Application.User.FullName;
                }
            }
        }
        partial void Visits_Filter(ref Expression<Func<Visit, bool>> filter)
        {
            if (!(this.Application.User.HasPermission(Permissions.CanEditVisit)))
            {
                if (this.Application.User.HasPermission(Permissions.CanManageMyVisit)) //sales person assigned to shop
                {
                    filter = e => e.VisitShop.ShopSalesPerson.aspnet_Profile.PropertyValuesString == this.Application.User.FullName;
                }
            }
        }

        partial void Contacts_Filter(ref Expression<Func<Contact, bool>> filter)
        {
            if (!(this.Application.User.HasPermission(Permissions.CanEditContact) 
                || this.Application.User.HasPermission(Permissions.CanSearchContact)
                || this.Application.User.HasPermission(Permissions.CanManageMyShop)
                || this.Application.User.HasPermission(Permissions.CanManageMyVisit)
                )) //if user has no one of these permissions it must be explicitly linked with contact
            {
                    filter = e => e.ContactShop.ShopSalesPerson.aspnet_Profile.PropertyValuesString == this.Application.User.FullName
                        || e.ContactSalesPerson.aspnet_Profile.PropertyValuesString == this.Application.User.FullName
                        || e.ContactCustomer.aspnet_Profile.PropertyValuesString == this.Application.User.FullName;
            }
        }

        partial void Addresses_Filter(ref Expression<Func<Address, bool>> filter)
        {
            if (!(this.Application.User.HasPermission(Permissions.CanEditContact)
                || this.Application.User.HasPermission(Permissions.CanSearchContact)
                || this.Application.User.HasPermission(Permissions.CanManageMyShop)
                || this.Application.User.HasPermission(Permissions.CanManageMyVisit)
                )) //if user has no one of these permissions it must be explicitly linked with contact
            {
                filter = e => e.Shop.ShopSalesPerson.aspnet_Profile.PropertyValuesString == this.Application.User.FullName
                    || e.SalesPerson.aspnet_Profile.PropertyValuesString == this.Application.User.FullName
                    || e.Customer.aspnet_Profile.PropertyValuesString == this.Application.User.FullName;
            }
        }
    }
}
